import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Iterator;
import java.util.Vector;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;


public class ButtonActionListener implements ActionListener
{

	private JPanel mPanel = null;
	private JPanel mDirectoryPanel = null;
	private JPanel mAttributesPanel = null;
	private JScrollPane mPictureScroll = null;
	private File [] mFiles = null;
	ButtonActionListener()
	{
		
	}
	
	public void setPanel(JPanel panel)
	{
		mPanel = panel;
		//mPanelRow2 = panel2;
		Component [] panels = panel.getComponents();
		for (int i = 0; i < panels.length; i++)
		{
			Component component = panels[i];
			if(component.getName() != null)
			{
				if(component.getName().compareTo("directoryTxtPanel") == 0)
				{
					mDirectoryPanel = (JPanel)component;
				}
				else if(component.getName().compareTo("attributesPanel") == 0)
				{
					mAttributesPanel = (JPanel)component;
				}
				else if(component.getName().compareTo("picturePanel") == 0)
				{
					mPictureScroll = (JScrollPane)component;
				}
			}
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e)
	{
		// TODO Auto-generated method stub
		if(e.getActionCommand().compareTo("open") == 0)
		{
			String curDirectory = Main.getLastDirectory(true);
			// get an open dialog box
			JFileChooser fc = null;
			if(curDirectory.length() != 0)
			{
				fc = new JFileChooser(curDirectory);
			}
			else
			{
				fc = new JFileChooser();
			}
			fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			int retVal = fc.showOpenDialog(mPanel);
			if(retVal == JFileChooser.APPROVE_OPTION)
			{
				// get the file we chose.
				File f = fc.getSelectedFile();
				String s = f.getAbsolutePath();
				
				Main.saveLastDirectory(true, s);
				
				mFiles = f.listFiles();
				
				Component [] components =  mDirectoryPanel.getComponents();
				JTextField txtField = null;
				for(int i = 0; i < components.length; i++)
				{
					// There is only one JTextField in this application, so we know which component
					// to extract based on what type it is.
					if(components[i] instanceof JTextField)
					{
						txtField = (JTextField)components[i];
						break;
					}
				}
				txtField.setText(s);
			}
			fc = null;
		}
		else if(e.getActionCommand().compareTo("preview") == 0)
		{
			// get our component associated with the scroll pane.
			PicturePanel picPane = (PicturePanel)mPictureScroll.getViewport().getView();
			
			Component [] components = mAttributesPanel.getComponents();
			JTextField attribText = null;
			int numRows = 0;
			for (int i = 0; i < components.length; i++)
			{
				if(components[i] instanceof JTextField)
				{
					attribText = (JTextField)components[i];
					break;
				}
			}
			numRows = Integer.parseInt(attribText.getText());
			if(numRows == 0) numRows = 1;
			
			FileNameExtensionFilter filter = new FileNameExtensionFilter("PNG file", "png");
			String fileContents = "";
			Vector<File> vFiles = new Vector<File>();
			Vector<Integer> vWidths = new Vector<Integer>();
			int mergedWidth = 0;
			int mergedHeight = 0;
			int longestWidth = 0;
			// retrieve all the widths and heights of the images
			if(mFiles == null)
			{
				JOptionPane.showMessageDialog(null, "Please choose a directory before previewing.");
			}
			else
			{
				for(int i = 0; i < mFiles.length; i++)
				{
					if(filter.accept(mFiles[i]) && mFiles[i].isDirectory() == false)
					{
						fileContents += mFiles[i].getAbsolutePath() + "\n";
						vFiles.add(mFiles[i]);
						try
						{
							BufferedImage img = ImageIO.read(mFiles[i]);
							vWidths.add(img.getWidth());
							mergedWidth += img.getWidth();
							if(img.getWidth() > longestWidth)
							{
								longestWidth = img.getWidth(); // for row padding. 
							}
							if(img.getHeight() > mergedHeight)
							{
								mergedHeight = img.getHeight(); // assuming the height is always the same... this should be more versatile.
							}
							img = null;
						}
						catch(Exception ex)
						{
							System.err.println("error reading image file: " + mFiles[i].getAbsolutePath());
						}
						
					}
				}
				filter = null; // finished using the filter object.
				int rowPadding = 0;
				if((mergedWidth/numRows)%longestWidth != 0) 
				{
					rowPadding = longestWidth;
				}
				
				BufferedImage mergedImage = new BufferedImage((mergedWidth/numRows)+rowPadding, mergedHeight*numRows, BufferedImage.TYPE_INT_ARGB);
				Graphics2D mergedGraphics = mergedImage.createGraphics();
				
				int curXLocation = 0;
				int curYLocation = 0;
				int curFrame = 0;
				int maxFrames = (vFiles.size()-1) / numRows;
				
				try
				{
					// layout the images based on the widths we received earlier.
					for(int i = 0; i < vFiles.size(); i++)
					{
						
						BufferedImage bi = ImageIO.read(vFiles.elementAt(i));
						mergedGraphics.drawImage(bi, curXLocation, curYLocation, null);
						bi = null;
						curXLocation += vWidths.elementAt(i);
						if(maxFrames <= curFrame)
						{
							curYLocation += mergedHeight;
							curXLocation = 0;
							curFrame = 0;
						}
						else
						{
							curFrame++;
						}
					}
				}
				catch(Exception ex)
				{
					
				}
				picPane.setPreferredSize(new Dimension(mergedImage.getWidth(), mergedImage.getHeight()));
				picPane.UpdateImage(mergedImage);
			}
			
		}
		else if(e.getActionCommand().compareTo("merge") == 0)
		{
			if(mFiles == null)
			{
				JOptionPane.showMessageDialog(null, "Please choose a directory before previewing.");
			}
			else
			{
				String curDirectory = Main.getLastDirectory(false);
				// merge the images; open a save box.
				JFileChooser fc = null;
				if(curDirectory.length() != 0)
				{
					fc = new JFileChooser(curDirectory);
				}
				else
				{
					fc = new JFileChooser();
				}
				fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
				int retVal = fc.showSaveDialog(mPanel);
				int numRows = 0;
				Component [] components = mAttributesPanel.getComponents();
				JTextField txtField = null;
				for(int i = 0; i < components.length; i++)
				{
					// There is only one JTextField in this application, so we know which component
					// to extract based on what type it is.
					if(components[i] instanceof JTextField)
					{
						txtField = (JTextField)components[i];
						break;
					}
				}
				numRows = Integer.parseInt(txtField.getText());
				if(numRows == 0) numRows = 1;
				if(retVal == JFileChooser.APPROVE_OPTION)
				{
					FileNameExtensionFilter filter = new FileNameExtensionFilter("PNG file", "png");
					String fileContents = "";
					Vector<File> vFiles = new Vector<File>();
					Vector<Integer> vWidths = new Vector<Integer>();
					int mergedWidth = 0;
					int mergedHeight = 0;
					int longestWidth = 0;
					for(int i = 0; i < mFiles.length; i++)
					{
						if(filter.accept(mFiles[i]) && mFiles[i].isDirectory() == false)
						{
							fileContents += mFiles[i].getAbsolutePath() + "\n";
							vFiles.add(mFiles[i]);
							try
							{
								BufferedImage img = ImageIO.read(mFiles[i]);
								vWidths.add(img.getWidth());
								mergedWidth += img.getWidth();
								if(img.getWidth() > longestWidth)
								{
									longestWidth = img.getWidth(); // for row padding. 
								}
								if(img.getHeight() > mergedHeight)
								{
									mergedHeight = img.getHeight(); // assuming the height is always the same... this should be more versatile.
								}
								img = null;
							}
							catch(Exception ex)
							{
								System.err.println("error reading image file: " + mFiles[i].getAbsolutePath());
							}
							
						}
					}
					filter = null; // finished using the filter object.
					int rowPadding = 0;
					if((mergedWidth/numRows)%longestWidth != 0) 
					{
						rowPadding = longestWidth;
					}
					// create a new file and save something in it.
					try
					{
						
						File file = fc.getSelectedFile();
						
						// save out our directory
						String s = file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(File.separator));
						Main.saveLastDirectory(false, s);
						
						BufferedImage mergedImage = new BufferedImage((mergedWidth/numRows)+rowPadding, mergedHeight*numRows, BufferedImage.TYPE_INT_ARGB);
						Graphics2D mergedGraphics = mergedImage.createGraphics();
						
						Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("png");
						ImageWriter writer = writers.next();
						
						ImageOutputStream ios = ImageIO.createImageOutputStream(file);
						writer.setOutput(ios);
						int curXLocation = 0;
						int curYLocation = 0;
						int curFrame = 0;
						int maxFrames = (vFiles.size()-1) / numRows;
						
						for(int i = 0; i < vFiles.size(); i++)
						{
							
							//BufferedImage first_bi, second_bi;
							//IIOImage first_IIOImage = new IIOImage(first_bi, null, null);
							//IIOImage second_IIOImage = new IIOImage(second_bi, null, null);
							
							BufferedImage bi = ImageIO.read(vFiles.elementAt(i));
							mergedGraphics.drawImage(bi, curXLocation, curYLocation, null);
							bi = null;
							curXLocation += vWidths.elementAt(i);
							if(maxFrames <= curFrame)
							{
								curYLocation += mergedHeight;
								curXLocation = 0;
								curFrame = 0;
							}
							else
							{
								curFrame++;
							}
						}
						
						IIOImage ioimg = new IIOImage(mergedImage, null, null);
						writer.write(null, ioimg, null);
						writer.dispose();
						ios.close();
						
						// clear memory.
						ioimg = null;
						ios = null;
						writer = null;
						writers = null;
						mergedGraphics = null;
						mergedImage = null;
						file = null;
						
						//FileOutputStream fos = new FileOutputStream(file);
						//fos.write(fileContents.getBytes());
						//fos.close();
					}
					catch(Exception ex)
					{
						ex.printStackTrace();
					}
				}
				fc = null;
			}
		}
	}

}
